package qlsl.androiddesign.api.http.service.baseservice;

import android.app.Activity;
import android.os.Handler;
import android.os.HandlerThread;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.TextView;

import com.alibaba.fastjson.JSONObject;
import com.itheima.pulltorefreshlib.PullToRefreshAdapterViewBase;
import com.itheima.pulltorefreshlib.PullToRefreshScrollView;

import org.reactivestreams.Publisher;

import java.lang.ref.WeakReference;
import java.net.UnknownHostException;

import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.FlowableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import qlsl.androiddesign.api.activity.R;
import qlsl.androiddesign.api.activity.baseactivity.CommonContract;
import qlsl.androiddesign.api.activity.baseactivity.FunctionActivity;
import qlsl.androiddesign.api.constant.MessageConstant;
import qlsl.androiddesign.api.constant.WhatConstant;
import qlsl.androiddesign.api.exception.NetError;
import qlsl.androiddesign.api.http.xutils.HttpProtocol;
import qlsl.androiddesign.api.util.commonutil.Log;
import qlsl.androiddesign.api.util.commonutil.ToastUtils;

/**
 * 功能：处理公共逻辑
 * 作者：郑朝军 on 2017/4/5 19:41
 * 邮箱：1250393285@qq.com
 * 公司：武汉智博创享科技有限公司
 */

public class ServiceBase<T extends CommonContract.CommonView> extends CommonServiceBase<T>
{
    protected WeakReference<FunctionActivity> m_weakActivity;// 引用弱引用防止内存泄露，需要注意其他地方使用

    public ServiceBase()
    {
    }

    public ServiceBase(FunctionActivity activity)
    {
        m_weakActivity = new WeakReference<FunctionActivity>(activity);
    }

    /**
     * 静态获取BaseService子类的路径
     * 以定位Log信息的具体位置
     *
     * @param destClass
     * @return
     */
    protected String getClassName(
            final Class<? extends ServiceBase> destClass)
    {
        return new Object()
        {
            public String getClassName()
            {
                return destClass.getName();
            }
        }.getClassName();
    }

    //--------------------------------------------Rxjava2.0与Xutils2.6结合START------------------------------------------
    /**
     * 验证数据是否有问题
     *
     * @param jo
     * @param e
     * @return
     */
    public boolean isDataInvalid(JSONObject jo, FlowableEmitter<Object> e)
    {
        if (e.isCancelled())
        {
            if (getV() == null)
            {
                return true;
            }
            ((Activity) getV()).runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                    getV().hideProgressBar();
                }
            });
            return true;
        }

        if (jo == null)
        {
            e.onError(new NetError(new UnknownHostException(MessageConstant.MSG_SERVER_FAILED),
                    NetError.MSG_NOCONNECT_FAILED));
            return true;
        }
        else if ("null".equals(jo.getString("msg"))
                && "fail".equals(jo.getString("msg")))
        {
            e.onError(new NetError(jo.getString("errorCode"), NetError.MSG_NODATA_FAILED));
            return true;
        }
        else if ("101000".equals(jo.getString("row")))
        {
            e.onError(new NetError(jo.getString("errorCode"), NetError.MSG_AUTH_FAILED));
            return true;
        }
        return false;
    }

    /**
     * 打印log日志
     *
     * @param protocol
     * @param jo
     * @param className
     * @param method
     */
    protected void outputMessageInfo(HttpProtocol protocol, JSONObject jo,
                                     String className, String method)
    {
        if (Log.isDebug)
        {
            Log.i("网络正在返回：" + method + "<br/>" + className
                    + "<br/>url：<font color=red>" + protocol.getUrl() + "</font><br/>params：" +
                    protocol.getParams() + "<br/>result：" + jo);
        }
    }

    /**
     * 打印log日志
     *
     * @param jo
     * @param className
     * @param method
     */
    protected void outputMessageInfo(JSONObject jo, String className, String method)
    {
        if (Log.isDebug)
        {
            Log.i("网络正在返回：" + method + "<br/>" + className + "<br/>result：" + jo);
        }
    }

    protected void outputMessageInfo(String status, String url, String params,
                                     String className, String method)
    {
        if (Log.isDebug)
        {
            if (MessageConstant.MSG_UNKOW_FAILED.equals(url))
            {
                Log.i("网络正在返回：" + method + "<br/>" + className + "<br/>url：" + url
                        + "<br/>params：" + params + "<br/>status：" + status);
            }
            else
            {
                Log.i("网络正在返回：" + method + "<br/>" + className
                        + "<br/>url：<a href=\"" + url + "\">" + url
                        + "</a><br/>params：" + params + "<br/>status：" + status);
            }
        }
    }

    /**
     * 隐藏ProgressBar,大量数据需要解析，解析时间漫长需要调用此方法
     */
    public void hideProgressBar()
    {
        if (getV() == null)
        {
            return;
        }
        ((Activity) getV()).runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                getV().hideProgressBar();
            }
        });
    }

    /**
     * 网络解析处理报错
     *
     * @param e
     * @param exception
     * @param className
     */
    public void outputException(FlowableEmitter<Object> e, Exception exception, String className)
    {
        if (Log.isDebug)
        {
            Log.cx("exception" + exception);
        }

        if (e.isCancelled())
        {
            return;
        }
        e.onError(new NetError(exception, className, NetError.MSG_SERVER_RESTART));
    }


    /**
     * 线程切换
     *
     * @return
     */
    public <T> FlowableTransformer<T, T> getScheduler()
    {
        return new FlowableTransformer<T, T>()
        {
            @Override
            public Publisher<T> apply(Flowable<T> upstream)
            {
                return upstream.subscribeOn(io.reactivex.schedulers.Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

    /**
     * 创建Subscriber 网络
     *
     * @param method
     * @return
     */
    public SubcriberBase createSubscriber(final String method)
    {
        return new SubcriberBase<Object>()
        {
            @Override
            protected void onFail(NetError error)
            {
                getV().hideProgressBar();
                String errors = showError(error);
                showEmptyView(errors);
                getV().showNetWorkFaildData(method, errors);
            }

            @Override
            public void onNext(Object object)
            {
                getV().hideProgressBar();
                getV().showNetWorkSucceedData(method, object);
            }
        };
    }

    /**
     * 创建Subscriber 网络
     * ProgressBar不显示
     *
     * @param method
     * @return
     */
    public SubcriberBase createSubscriberWithOutShow(final String method)
    {
        return new SubcriberBase<Object>()
        {
            @Override
            protected void onFail(NetError error)
            {
                String errors = showError(error);
                showEmptyView(errors);
                getV().showNetWorkFaildData(method, errors);
            }

            @Override
            public void onNext(Object object)
            {
                getV().showNetWorkSucceedData(method, object);
            }
        };
    }

    /**
     * 创建Subscriber 数据库
     *
     * @param method
     * @return
     */
    public SubcriberBase createSubscriberDb(final String method)
    {
        return new SubcriberBase<Object>()
        {
            @Override
            protected void onFail(NetError error)
            {
                getV().hideProgressBar();
                String errors = showError(error);
                showEmptyView(errors);
                getV().showFaildDbData(method, errors);
            }

            @Override
            public void onNext(Object object)
            {
                getV().hideProgressBar();
                getV().showDbSucceedData(method, object);
            }
        };
    }

    /**
     * 创建Subscriber 数据库
     * ProgressBar不显示
     *
     * @param method
     * @return
     */
    public SubcriberBase createSubscriberWithOutShowDb(final String method)
    {
        return new SubcriberBase<Object>()
        {
            @Override
            protected void onFail(NetError error)
            {
                String errors = showError(error);
                showEmptyView(errors);
                getV().showFaildDbData(method, errors);
            }

            @Override
            public void onNext(Object object)
            {
                getV().showDbSucceedData(method, object);
            }
        };
    }

    /**
     * 创建Subscriber 其他
     *
     * @param method
     * @return
     */
    public SubcriberBase createSubscriberOther(final String method)
    {
        return new SubcriberBase<Object>()
        {
            @Override
            protected void onFail(NetError error)
            {
                getV().hideProgressBar();
                String errors = showError(error);
                showEmptyView(errors);
                getV().showFaildOtherData(method, errors);
            }

            @Override
            public void onNext(Object object)
            {
                getV().hideProgressBar();
                getV().showOtherSucceedData(method, object);
            }
        };
    }

    /**
     * 创建Subscriber 其他
     * ProgressBar不显示
     *
     * @param method
     * @return
     */
    public SubcriberBase createSubscriberWithOutShowOther(final String method)
    {
        return new SubcriberBase<Object>()
        {
            @Override
            protected void onFail(NetError error)
            {
                String errors = showError(error);
                showEmptyView(errors);
                getV().showFaildOtherData(method, errors);
            }

            @Override
            public void onNext(Object object)
            {
                getV().showOtherSucceedData(method, object);
            }
        };
    }

    /**
     * 显示异常
     *
     * @param error
     * @return
     */
    public String showError(NetError error)
    {
        String errorMsg = "";
        if (error != null)
        {
            switch (error.getType())
            {
                case NetError.MSG_PARSEERROR_FAILED:
                    errorMsg = MessageConstant.MSG_PARSEERROR_FAILED;
                    break;

                case NetError.MSG_AUTH_FAILED:
                    errorMsg = MessageConstant.MSG_AUTH_FAILED;
                    break;

                case NetError.MSG_BUSINESS_FAILED:
                    errorMsg = Log.isDebug ? "业务异常" + error.getMessage() : error.getMessage();
                    break;

                case NetError.MSG_NOCONNECT_FAILED:
                    errorMsg = MessageConstant.MSG_SERVER_FAILED;
                    break;

                case NetError.MSG_NODATA_FAILED:
                    errorMsg = MessageConstant.MSG_NODATA_FAILED;
                    break;

                case NetError.MSG_OTHER_FAILED:
                    errorMsg = error + "";
                    break;
                case NetError.MSG_SERVER_FAILED:
                    errorMsg = MessageConstant.MSG_SERVER_FAILED;
                    break;
                case NetError.MSG_UNKOW_FAILED:
                    errorMsg = MessageConstant.MSG_UNKOW_FAILED;
                    break;
                case NetError.MSG_ECPITON_FAILED:
                    errorMsg = "网络异常" + "\n  异常运行窗口" + error.getMessage();
                    break;
                case NetError.MSG_SERVER_RESTART:
                    errorMsg = MessageConstant.MSG_SERVER_RESTART;
                    break;
            }
        }
        return errorMsg;
    }

    /**
     * 显示异常数据
     *
     * @param errorMsg
     */
    public void showEmptyView(String errorMsg)
    {
        TextView tv_empty = (TextView) getV().findView(R.id.tv_empty);
        if (tv_empty == null)
        {
            ToastUtils.showNoDataToast(errorMsg);
            return;
        }
        tv_empty.setText(getV().getString(R.string.no_data));
        ViewGroup parentView = (ViewGroup) getV().findView(R.id.emptyParentView);
        if (parentView == null) return;
        View childView = parentView.getChildAt(0);
        if (childView instanceof PullToRefreshAdapterViewBase)
        {
            PullToRefreshAdapterViewBase<?> refreshView = (PullToRefreshAdapterViewBase<?>)
                    childView;
            tv_empty.setText(errorMsg);
            refreshView.onRefreshComplete();
            refreshView.setEmptyView(tv_empty);
        }
        else if (childView instanceof AdapterView)
        {
            AdapterView<?> adapterView = (AdapterView<?>) childView;
            tv_empty.setText(errorMsg);
            adapterView.setEmptyView(tv_empty);
        }
        PullToRefreshScrollView refreshView = (PullToRefreshScrollView) getV().findView(R.id
                .refreshScrollView);
        if (refreshView != null)
        {
            refreshView.onRefreshComplete();
        }
    }
    //--------------------------------------------Rxjava2.0与Xutils2.6结合END--------------------------------------------

    //--------------------------------------------Handler与HandlerThread------------------------------------------------
    public interface ServiceBaseHandlerThreadDelegate
    {
        JSONObject serviceBaseHandlerThreadCallBack(Handler handler);
    }

    public void HandlerThreadWithOutShow(final String method, final String className, final
    ServiceBaseHandlerThreadDelegate delegate)
    {
        final Handler handler = getHandler(method);
        new HandlerThread(className)
        {
            public void run()
            {
                try
                {
                    JSONObject jo = delegate.serviceBaseHandlerThreadCallBack(handler);
                    outputMessageInfo(jo, className, method);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    handler.sendMessage(handler.obtainMessage(WhatConstant.WHAT_OTHER_DATA_FAIL, e));
                }
            }
        }.start();
    }

    public void HandlerThread(final String method, final String className, final ServiceBaseHandlerThreadDelegate
            delegate)
    {
        getV().showProgressBar();
        final Handler handler = getHandler(method);
        new HandlerThread(className)
        {
            public void run()
            {
                try
                {
                    JSONObject jo = delegate.serviceBaseHandlerThreadCallBack(handler);
                    outputMessageInfo(jo, className, method);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    handler.sendMessage(handler.obtainMessage(WhatConstant.WHAT_OTHER_DATA_FAIL, e));
                }
            }
        }.start();
    }

    protected Handler getHandler(final String method)
    {
        final Handler handler = new Handler()
        {
            public void handleMessage(android.os.Message msg)
            {
                getV().hideProgressBar();
                switch (msg.what)
                {
                    case WhatConstant.WHAT_NET_DATA_SUCCESS:
                        getV().showNetWorkSucceedData(method, msg.obj);
                        break;
                    case WhatConstant.WHAT_NET_DATA_FAIL:
                        getV().showNetWorkFaildData(method, msg.obj);
                        break;
                    case WhatConstant.WHAT_DB_DATA_SUCCESS:
                        getV().showDbSucceedData(method, msg.obj);
                        break;
                    case WhatConstant.WHAT_DB_DATA_FAIL:
                        getV().showFaildDbData(method, msg.obj);
                        break;
                    case WhatConstant.WHAT_OTHER_DATA_SUCCESS:
                        getV().showOtherSucceedData(method, msg.obj);
                        break;
                    case WhatConstant.WHAT_OTHER_DATA_FAIL:
                        getV().showFaildOtherData(method, msg.obj);
                        break;
                }
            }
        };
        return handler;
    }

    /**
     * 验证数据是否有问题
     *
     * @param jo
     * @return
     */
    public static boolean isDataInvalid(JSONObject jo, Handler handler)
    {
        if (jo == null)
        {
            handler.sendMessage(handler.obtainMessage(WhatConstant.WHAT_NET_DATA_FAIL,
                    MessageConstant.MSG_CLIENT_FAILED));
            return true;
        }
        else if ("null".equals(jo.getString("errorCode"))
                && "fail".equals(jo.getString("msg")))
        {
            handler.sendMessage(handler.obtainMessage(WhatConstant.WHAT_NET_DATA_SUCCESS,
                    MessageConstant.MSG_OTHER_FAILED));
            return true;
        }
        else if ("101000".equals(jo.getString("row")))
        {
            handler.sendMessage(handler.obtainMessage(WhatConstant.WHAT_NET_DATA_SUCCESS,
                    MessageConstant.MSG_AUTH_FAILED));
            return true;
        }
        return false;
    }
}
